package com.blog.cmrpersonalblog.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.blog.cmrpersonalblog.dto.article.request.ArticleAuditRequest;
import com.blog.cmrpersonalblog.dto.article.request.ArticleBatchOperationRequest;
import com.blog.cmrpersonalblog.dto.article.request.ArticleQueryRequest;
import com.blog.cmrpersonalblog.dto.article.response.ArticleDetailResponse;
import com.blog.cmrpersonalblog.dto.article.response.ArticleManagementResponse;
import com.blog.cmrpersonalblog.entity.Article;
import com.blog.cmrpersonalblog.entity.ArticleTag;
import com.blog.cmrpersonalblog.mapper.ArticleMapper;
import com.blog.cmrpersonalblog.service.ArticleManagementService;
import com.blog.cmrpersonalblog.service.ArticleTagRelationService;
import com.blog.cmrpersonalblog.service.MarkdownService;
import com.blog.cmrpersonalblog.service.UserActivityService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文章管理服务实现类
 */
@Slf4j
@Service
public class ArticleManagementServiceImpl implements ArticleManagementService {

   @Resource
    private ArticleMapper articleMapper;

   @Resource
    private MarkdownService markdownService;

   @Resource
    private UserActivityService userActivityService;

   @Resource
    private ArticleTagRelationService articleTagRelationService;

    @Override
    public IPage<ArticleManagementResponse> getArticleList(ArticleQueryRequest queryRequest) {
        Page<ArticleManagementResponse> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        return articleMapper.selectArticleManagementPage(page, queryRequest);
    }

    @Override
    public ArticleDetailResponse getArticleDetail(Long articleId) {
        if (articleId == null) {
            return null;
        }
        
        ArticleDetailResponse detail = articleMapper.selectArticleDetailById(articleId);
        if (detail != null) {
            // 转换Markdown为HTML
            if (detail.getContent() != null) {
                detail.setHtmlContent(markdownService.convertToHtml(detail.getContent()));
            }
            
            // 获取文章的标签信息
            List<ArticleTag> tags = articleTagRelationService.getTagsByArticleId(articleId);
            if (tags != null && !tags.isEmpty()) {
                List<ArticleDetailResponse.ArticleTagInfo> articleTags = tags.stream()
                    .map(tag -> {
                        ArticleDetailResponse.ArticleTagInfo tagInfo = new ArticleDetailResponse.ArticleTagInfo();
                        tagInfo.setId(tag.getId());
                        tagInfo.setName(tag.getName());
                        tagInfo.setColor(tag.getColor());
                        tagInfo.setDescription(tag.getDescription());
                        tagInfo.setIcon(tag.getIcon());
                        tagInfo.setUseCount(tag.getUseCount());
                        return tagInfo;
                    })
                    .collect(Collectors.toList());
                detail.setArticleTags(articleTags);
            }
            
            // 设置标签数量
            int tagCount = articleTagRelationService.countTagsByArticleId(articleId);
            detail.setTagCount(tagCount);
        }
        
        return detail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditArticle(ArticleAuditRequest auditRequest, Long auditorId) {
        try {
            if (!auditRequest.isValidAuditResult()) {
                throw new RuntimeException("无效的审核结果");
            }

            // 检查文章是否存在且状态为待审核
            Article article = articleMapper.selectById(auditRequest.getArticleId());
            if (article == null) {
                throw new RuntimeException("文章不存在");
            }
            if (article.getStatus() != 3) {
                throw new RuntimeException("文章状态不是待审核，无法审核");
            }

            // 更新审核信息
            int result = articleMapper.updateArticleAuditInfo(
                auditRequest.getArticleId(),
                auditRequest.getAuditResult(),
                auditorId,
                auditRequest.getAuditRemark(),
                auditRequest.getAuditReason()
            );

            if (result > 0) {
                // 记录审核活动
                String activityType = auditRequest.isApprove() ? "ARTICLE_APPROVED" : "ARTICLE_REJECTED";
                String description = auditRequest.isApprove() ? "审核通过文章" : "审核拒绝文章";
                
                userActivityService.recordActivity(auditorId, activityType, description,
                    auditRequest.getArticleId(), "article", "SUCCESS", null);

                log.info("文章审核成功: articleId={}, result={}, auditorId={}", 
                    auditRequest.getArticleId(), auditRequest.getAuditResult(), auditorId);
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("文章审核失败", e);
            throw new RuntimeException("文章审核失败: " + e.getMessage());
        }
    }

    /**
     *
     * @param batchRequest 批量操作请求
     * @param operatorId 操作人ID
     * @return 操作结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchOperateArticles(ArticleBatchOperationRequest batchRequest, Long operatorId) {
        Map<String, Object> result = new HashMap<>();
        List<String> successIds = new ArrayList<>();
        List<String> failedIds = new ArrayList<>();
        
        try {
            if (!batchRequest.isValidOperationType()) {
                throw new RuntimeException("无效的操作类型");
            }

            ArticleBatchOperationRequest.OperationType operationType = batchRequest.getOperationTypeEnum();
            int affectedRows = switch (operationType) {
                case APPROVE, PUBLISH -> articleMapper.batchUpdateArticleStatus(batchRequest.getArticleIds(), 1, operatorId);
                case REJECT -> articleMapper.batchUpdateArticleStatus(batchRequest.getArticleIds(), 4, operatorId);
                case UNPUBLISH -> articleMapper.batchUpdateArticleStatus(batchRequest.getArticleIds(), 5, operatorId);
                case TOP -> articleMapper.batchUpdateArticleTop(batchRequest.getArticleIds(), 1, operatorId);
                case UNTOP -> articleMapper.batchUpdateArticleTop(batchRequest.getArticleIds(), 0, operatorId);
                case DELETE -> articleMapper.batchDeleteArticles(batchRequest.getArticleIds(), operatorId);
                default -> throw new RuntimeException("不支持的操作类型: " + operationType.getDescription());
            };

            // 记录操作结果
            if (affectedRows > 0) {
                for (Long articleId : batchRequest.getArticleIds()) {
                    successIds.add(articleId.toString());
                }
                
                // 记录批量操作活动
                userActivityService.recordActivity(operatorId, "BATCH_ARTICLE_OPERATION", 
                    "批量操作文章: " + operationType.getDescription(),
                    null, "article", "SUCCESS", 
                    Map.of("operation", operationType.getCode(), "count", affectedRows));
                
                log.info("批量操作文章成功: operation={}, count={}, operatorId={}", 
                    operationType.getCode(), affectedRows, operatorId);
            }

            result.put("success", true);
            result.put("message", "批量操作完成");
            result.put("affectedRows", affectedRows);
            result.put("successIds", successIds);
            result.put("failedIds", failedIds);
            
        } catch (Exception e) {
            log.error("批量操作文章失败", e);
            result.put("success", false);
            result.put("message", "批量操作失败: " + e.getMessage());
            result.put("affectedRows", 0);
            result.put("successIds", successIds);
            result.put("failedIds", batchRequest.getArticleIds().stream().map(Object::toString).toList());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publishArticle(Long articleId, Long operatorId) {
        try {
            Article article = articleMapper.selectById(articleId);
            if (article == null) {
                throw new RuntimeException("文章不存在");
            }

            // 更新文章状态为已发布
            article.setStatus(1);
            article.setPublishTime(LocalDateTime.now());
            article.setUpdateTime(LocalDateTime.now());
            
            int result = articleMapper.updateById(article);
            if (result > 0) {
                // 记录发布活动
                userActivityService.recordActivity(operatorId, "ARTICLE_PUBLISHED", "发布文章",
                    articleId, "article", "SUCCESS", null);
                
                log.info("文章发布成功: articleId={}, operatorId={}", articleId, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("文章发布失败", e);
            throw new RuntimeException("文章发布失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unpublishArticle(Long articleId, Long operatorId, String reason) {
        try {
            Article article = articleMapper.selectById(articleId);
            if (article == null) {
                throw new RuntimeException("文章不存在");
            }

            // 更新文章状态为已下架
            article.setStatus(5);
            article.setUpdateTime(LocalDateTime.now());
            
            int result = articleMapper.updateById(article);
            if (result > 0) {
                // 记录下架活动
                userActivityService.recordActivity(operatorId, "ARTICLE_UNPUBLISHED", "下架文章",
                    articleId, "article", "SUCCESS", Map.of("reason", reason != null ? reason : ""));
                
                log.info("文章下架成功: articleId={}, operatorId={}, reason={}", articleId, operatorId, reason);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("文章下架失败", e);
            throw new RuntimeException("文章下架失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean topArticle(Long articleId, boolean isTop, Long operatorId) {
        try {
            Article article = articleMapper.selectById(articleId);
            if (article == null) {
                throw new RuntimeException("文章不存在");
            }

            // 更新文章置顶状态
            article.setIsTop(isTop ? 1 : 0);
            article.setUpdateTime(LocalDateTime.now());
            
            int result = articleMapper.updateById(article);
            if (result > 0) {
                // 记录置顶活动
                String activityType = isTop ? "ARTICLE_TOPPED" : "ARTICLE_UNTOPPED";
                String description = isTop ? "置顶文章" : "取消置顶文章";
                
                userActivityService.recordActivity(operatorId, activityType, description,
                    articleId, "article", "SUCCESS", null);
                
                log.info("文章置顶操作成功: articleId={}, isTop={}, operatorId={}", articleId, isTop, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("文章置顶操作失败", e);
            throw new RuntimeException("文章置顶操作失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteArticle(Long articleId, Long operatorId) {
        try {
            Article article = articleMapper.selectById(articleId);
            if (article == null) {
                throw new RuntimeException("文章不存在");
            }

            // 更新文章状态为已删除
            article.setStatus(2);
            article.setUpdateTime(LocalDateTime.now());
            
            int result = articleMapper.updateById(article);
            if (result > 0) {
                // 记录删除活动
                userActivityService.recordActivity(operatorId, "ARTICLE_DELETED", "删除文章",
                    articleId, "article", "SUCCESS", null);
                
                log.info("文章删除成功: articleId={}, operatorId={}", articleId, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("文章删除失败", e);
            throw new RuntimeException("文章删除失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean restoreArticle(Long articleId, Long operatorId) {
        try {
            Article article = articleMapper.selectById(articleId);
            if (article == null) {
                throw new RuntimeException("文章不存在");
            }
            if (article.getStatus() != 2) {
                throw new RuntimeException("只能恢复已删除的文章");
            }

            // 恢复文章状态为草稿
            article.setStatus(0);
            article.setUpdateTime(LocalDateTime.now());
            
            int result = articleMapper.updateById(article);
            if (result > 0) {
                // 记录恢复活动
                userActivityService.recordActivity(operatorId, "ARTICLE_RESTORED", "恢复文章",
                    articleId, "article", "SUCCESS", null);
                
                log.info("文章恢复成功: articleId={}, operatorId={}", articleId, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("文章恢复失败", e);
            throw new RuntimeException("文章恢复失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getArticleStatistics() {
        return articleMapper.selectArticleStatistics();
    }

    @Override
    public Long getPendingAuditCount() {
        return articleMapper.selectPendingAuditCount();
    }

    @Override
    public Map<String, Long> getArticleStatusDistribution() {
        List<Map<String, Object>> distribution = articleMapper.selectArticleStatusDistribution();
        Map<String, Long> result = new HashMap<>();

        for (Map<String, Object> item : distribution) {
            String statusName = (String) item.get("statusName");
            Long count = ((Number) item.get("count")).longValue();
            result.put(statusName, count);
        }

        return result;
    }

    @Override
    public List<ArticleManagementResponse> getPopularArticles(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 10;
        }
        return articleMapper.selectPopularArticles(limit);
    }

    @Override
    public List<ArticleManagementResponse> getLatestArticles(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 10;
        }
        return articleMapper.selectLatestArticles(limit);
    }

    @Override
    public IPage<ArticleManagementResponse> searchArticles(String keyword, Long current, Long size) {
        Page<ArticleManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return articleMapper.searchArticles(page, keyword);
    }

    @Override
    public IPage<ArticleManagementResponse> getUserArticles(Long userId, Long current, Long size) {
        Page<ArticleManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return articleMapper.selectUserArticleManagementPage(page, userId);
    }

    @Override
    public IPage<ArticleManagementResponse> getCategoryArticles(Long categoryId, Long current, Long size) {
        Page<ArticleManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return articleMapper.selectCategoryArticleManagementPage(page, categoryId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateArticleStats(Long articleId, String field, Integer increment) {
        try {
            articleMapper.updateArticleStats(articleId, field, increment);
            return true;
        } catch (Exception e) {
            log.error("更新文章统计数据失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recalculateArticleStats(Long articleId) {
        try {
            int result = articleMapper.recalculateArticleStats(articleId);
            return result > 0;
        } catch (Exception e) {
            log.error("重新计算文章统计数据失败", e);
            return false;
        }
    }
}
